﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.Creation;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;

namespace Assist
{
	public class ElementAssistFunc
	{
        public static FaceArray GetElementFaces(UIApplication uiApp, Autodesk.Revit.DB.Document doc, Element e)
		{
			FaceArray faceArray = new FaceArray();
			Application create = uiApp.Application.Create;
			new ReferenceArray();
			Options options = create.NewGeometryOptions();
			options.ComputeReferences = true;
			options.View = doc.ActiveView;
			List<GeometryObject> geometryObjectArray = RevitVersionFuncs.GetGeometryObjectArray(e.get_Geometry(options));
			for (int i = 0; i < geometryObjectArray.Count; i++)
			{
				GeometryObject geometryObject = geometryObjectArray[i];
				if (geometryObject is GeometryInstance)
				{
					ElementAssistFunc.GetFaces(geometryObject, ref faceArray);
				}
				else if (geometryObject is Solid)
				{
					foreach (object obj in (geometryObject as Solid).Faces)
					{
						Face face = (Face)obj;
						faceArray.Append(face);
					}
				}
			}
			return faceArray;
		}

		public static bool GetFaces(object geoObject, ref FaceArray arFaces)
		{
			foreach (object obj in RevitVersionFuncs.GetGeometryObjectArray((geoObject as GeometryInstance).GetInstanceGeometry()))
			{
				if (obj is GeometryInstance)
				{
					return ElementAssistFunc.GetFaces(obj, ref arFaces);
				}
				if (obj is Solid)
				{
					foreach (object obj2 in (obj as Solid).Faces)
					{
						Face face = (Face)obj2;
						arFaces.Append(face);
					}
				}
			}
			return true;
		}

        public static List<Line> GetElementEdges(UIApplication uiApp, Autodesk.Revit.DB.Document doc, Element e)
		{
			List<Line> result = new List<Line>();
			Application create = uiApp.Application.Create;
			new ReferenceArray();
			Options options = create.NewGeometryOptions();
			options.ComputeReferences = true;
			options.View = doc.ActiveView;
			List<GeometryObject> geometryObjectArray = RevitVersionFuncs.GetGeometryObjectArray(e.get_Geometry(options));
			int i = 0;
			while (i < geometryObjectArray.Count)
			{
				GeometryObject geometryObject = geometryObjectArray[i];
				if (geometryObject is GeometryInstance)
				{
					using (List<GeometryObject>.Enumerator enumerator = RevitVersionFuncs.GetGeometryObjectArray((geometryObject as GeometryInstance).GetInstanceGeometry()).GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							GeometryObject geometryObject2 = enumerator.Current;
							ElementAssistFunc.GetLineEdgesInSolid(geometryObject2 as Solid, ref result);
						}
						goto IL_B0;
					}
					goto IL_99;
				}
				goto IL_99;
				IL_B0:
				i++;
				continue;
				IL_99:
				if (geometryObject is Solid)
				{
					ElementAssistFunc.GetLineEdgesInSolid(geometryObject as Solid, ref result);
					goto IL_B0;
				}
				goto IL_B0;
			}
			return result;
		}

		private static void GetLineEdgesInSolid(Solid solid, ref List<Line> arEdges)
		{
			if (null != solid)
			{
				EdgeArray edges = solid.Edges;
				for (int i = 0; i < edges.Size; i++)
				{
                    Edge edge = edges.get_Item(i);
					if (edge.Tessellate().Count == 2)
					{
						Line line = edge.AsCurve() as Line;
						if (line != null && object.Equals(line.GetEndPoint(0).Z, line.GetEndPoint(1).Z))
						{
							arEdges.Add(line);
						}
					}
				}
			}
		}

		public static IList<XYZ> Intersect(Element thisElem, Element otherElem)
		{
			IList<XYZ> list = new List<XYZ>();
			GeometryElement ge = thisElem.get_Geometry(new Options());
			List<Solid> list2 = new List<Solid>();
			foreach (GeometryObject geometryObject in RevitVersionFuncs.GetGeometryObjectArray(ge))
			{
				if (geometryObject is Solid)
				{
					Solid item = geometryObject as Solid;
					list2.Add(item);
				}
				else if (geometryObject is GeometryInstance)
				{
					using (List<GeometryObject>.Enumerator enumerator2 = RevitVersionFuncs.GetGeometryObjectArray((geometryObject as GeometryInstance).GetInstanceGeometry()).GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							if (enumerator2.Current is Solid)
							{
								Solid item2 = geometryObject as Solid;
								list2.Add(item2);
							}
						}
					}
				}
			}
			GeometryElement ge2 = otherElem.get_Geometry(new Options());
			List<Solid> list3 = new List<Solid>();
			foreach (GeometryObject geometryObject2 in RevitVersionFuncs.GetGeometryObjectArray(ge2))
			{
				if (geometryObject2 is Solid)
				{
					Solid item3 = geometryObject2 as Solid;
					list3.Add(item3);
				}
				else if (geometryObject2 is GeometryInstance)
				{
					using (List<GeometryObject>.Enumerator enumerator2 = RevitVersionFuncs.GetGeometryObjectArray((geometryObject2 as GeometryInstance).GetInstanceGeometry()).GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							if (enumerator2.Current is Solid)
							{
								Solid item4 = geometryObject2 as Solid;
								list3.Add(item4);
							}
						}
					}
				}
			}
			foreach (Solid solid in list2)
			{
				if (solid == null)
				{
					break;
				}
				EdgeArray edges = solid.Edges;
				foreach (Solid solid2 in list3)
				{
					if (!(solid2 == null))
					{
						EdgeArray edges2 = solid2.Edges;
						foreach (object obj in edges)
						{
							Curve curve = ((Edge)obj).AsCurve();
							foreach (object obj2 in edges2)
							{
								Curve curve2 = ((Edge)obj2).AsCurve();
								IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
								curve.Intersect(curve2, out intersectionResultArray);
								if (intersectionResultArray != null)
								{
									XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
									list.Add(xyzpoint);
								}
							}
						}
					}
				}
			}
			return list;
		}
	}
}
